home *** CD-ROM | disk | FTP | other *** search
-
- /* IconView.m */
-
- #import <objc/List.h>
- #import <appkit/Bitmap.h>
- #import <appkit/Listener.h>
- #import <appkit/graphics.h>
- #import <dpsclient/psops.h>
- #import <dpsclient/wraps.h>
- #import <strings.h>
- #import <libc.h>
- #import <math.h>
- #import "MyApp.h"
- #import "DockSpeaker.h"
- #import "IconView.h"
-
- #define UPPER_RIGHT 1
- #define LOWER_RIGHT 2
-
- @implementation IconView
-
- + new:(char *)name :icon :(int)xCoord :(int)yCoord
- {
- self = [super new];
-
- /* copy the app's name */
- appName = (char *)malloc(strlen(name) + 1);
- strcpy(appName, name);
-
- /* initialize bitmap locations */
- bitmap = icon;
- activeBitmap = [Bitmap findBitmapFor:"active"];
-
- /* save location in dock grid */
- xGridLocation = xCoord;
- yGridLocation = yCoord;
-
- /* figure out if we're the dock window */
- if (!strcmp(appName, "Dock")) {
- theDock = YES;
- altDocAppHidden = NO;
- }
-
- /* initialize */
- highLighted = NO;
- active = NO;
- appsPSContext = 0;
-
- return self;
- }
-
- - initialize:list :(int)minX :(int)minY :(int)maxX :(int)maxY
- /* give the dock the bounding box and list of all app windows */
- {
- xMin = minX;
- xMax = maxX;
- yMin = minY;
- yMax = maxY;
-
- windowList = list;
-
- /* create the drawing order lists for moving diagonally */
- upperRight = [self createOrderedListForCorner:UPPER_RIGHT];
- lowerRight = [self createOrderedListForCorner:LOWER_RIGHT];
-
- return self;
- }
-
- - createOrderedListForCorner:(int)corner
- /* returns a list of windows ordered based on the corner parameter */
- /* (this is the order in which they should be moved when moving toward */
- /* this corner */
- {
- int i, x1, y1, x2, y2, j;
- id list, tempList, iconWindow;
-
- list = [List new];
- tempList = [List new];
- i = [windowList count];
-
- /* insert all windows into the temporary list (ordered by x position) */
- while (i--) {
- iconWindow = [windowList objectAt:i];
- [[iconWindow contentView] coordinates:&x1 :&y1];
-
- j = 0;
- while (j < [tempList count]) {
- [[[tempList objectAt:j] contentView] coordinates:&x2 :&y2];
-
- /* sort by x position */
- if (corner == UPPER_RIGHT && x1 >= x2) {
- break;
- } else if (x1 >= x2) {
- break;
- }
- j++;
- }
- if (j == [tempList count]) {
- [tempList addObject:iconWindow];
- } else if (![tempList insertObject:iconWindow at:j]) {
- [tempList addObject:iconWindow];
- }
- }
-
- i = [tempList count];
-
- /* insert tempList windows into the final list, sorted by x and y */
- while (i--) {
- iconWindow = [tempList objectAt:i];
- [[iconWindow contentView] coordinates:&x1 :&y1];
-
- j = 0;
- while (j < [list count]) {
- [[[list objectAt:j] contentView] coordinates:&x2 :&y2];
-
- /* sort by y */
- if (corner == UPPER_RIGHT && x1 >= x2 && y1 >= y2) {
- break;
- } else if (x1 >= x2 && y1 <= y2) {
- break;
- }
- j++;
- }
- if (j == [list count]) {
- [list addObject:iconWindow];
- } else if (![list insertObject:iconWindow at:j]) {
- [list addObject:iconWindow];
- }
- }
-
- [tempList free];
-
- return list;
- }
-
- - drawSelf:(const NXRect *)rects :(int)rectCount
- {
- NXRect drawRect;
- int numBitmaps;
- NXPoint origin, activePoint;
-
- /* initialize a drawing rectangle */
- drawRect.origin.x = drawRect.origin.y = 0.0;
- drawRect.size.width = drawRect.size.height = 64.0;
- origin.x = origin.y = 8.0;
-
- if (!theDock) {
- /* if we're not the dock, draw our bezel */
- NXDrawButton(&drawRect, 0);
- NXInsetRect(&drawRect, 1.0, 1.0);
- NXDrawButton(&drawRect, 0);
- NXInsetRect(&drawRect, -1.0, -1.0);
-
- /* draw our 48x48-bit icon */
- [bitmap composite:NX_SOVER toPoint:&origin];
- activePoint.x = 64.0 - 2.0 - 18.0;
- activePoint.y = drawRect.origin.y + 4.0;
-
- /* draw the three dots if our program isn't active */
- if (!active) {
- [activeBitmap composite:NX_COPY toPoint:&activePoint];
- }
-
- /* highlight ourself if we're getting our app to run or unhide */
- if (highLighted) {
- NXInsetRect(&drawRect, 2.0, 2.0);
- NXHighlightRect(&drawRect);
- }
- } else {
- /* we're the dock so just copy our 64x64-bit icon into ourself */
- origin.x = origin.y = 0.0;
- [bitmap composite:NX_COPY toPoint:&origin];
- }
-
- return self;
- }
-
- #define MOVEMASK (NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK)
- - mouseDown:(NXEvent *)theEvent
- {
- NXPoint mouseDownLocation;
- NXEvent *currentEvent;
- NXCoord oldX, oldY, newX, newY, dx, dy, x, y;
- NXRect frameRect;
- int windowNum;
-
- /* if we're not the dock, see if we should unhide our application */
- if (!theDock) {
- [self handleNonDock:theEvent];
- return self;
- }
-
- /* hide or unhide the dock's menus and icon window if a double click */
- if (theEvent->data.mouse.click == 2) {
- [self hideOrUnhide];
- }
-
- [window addToEventMask:MOVEMASK];
-
- /* get the dock window's location */
- [window getFrame:&frameRect];
-
- /* convert the mouse's location to global (screen) coordinates */
- mouseDownLocation = theEvent->location;
- PScurrenttoscreen(mouseDownLocation.x, mouseDownLocation.y, &oldX, &oldY);
-
- /* initialization */
- newX = frameRect.origin.x;
- newY = frameRect.origin.y;
-
- currentEvent = [NXApp getNextEvent:MOVEMASK];
-
- while (currentEvent->type != NX_MOUSEUP) {
- /* things get messed up if we move our window and ask the window */
- /* to convert our mouse location to screen coordinates, so we */
- /* use this call instead to get the mouse's screen location */
- PScurrentmouse(0, &x, &y);
-
- /* offset from previous mouse location */
- dx = x - oldX;
- dy = y - oldY;
-
- /* compute the dock window's proposed origin */
- newX = dx + frameRect.origin.x;
- newY = dy + frameRect.origin.y;
-
- /* make sure this is ok (and fix it if not) */
- [self checkCoords:&newX :&newY];
-
- /* move everyone the correct amount */
- [self moveWindows:(newX - frameRect.origin.x)
- :(newY - frameRect.origin.y)];
-
- /* get our new origin and save the current mouse location */
- [window getFrame:&frameRect];
- oldX = x;
- oldY = y;
-
- /* wait for another mouse event */
- currentEvent = [NXApp getNextEvent:MOVEMASK];
- }
-
- /* impose the NeXT dock's grid behaviour on the window positions */
- [self snapToGrid:&newX :&newY];
- [self moveWindows:(newX - frameRect.origin.x)
- :(newY - frameRect.origin.y)];
-
- return self;
- }
-
- - checkCoords:(float *)x :(float *)y
- /* constrain the dock window's location based on the bounding box */
- {
- float maxX, maxY;
-
- if (*x < 4) *x = 4;
- if (*y < 0) *y = 0;
-
- maxX = (xMax - xMin) * 64.0 + 4.0;
- maxY = (yMax - yMin) * 64.0;
-
- if (*y > maxY) *y = maxY;
-
- if (*x > maxX) *x = maxX;
-
- return self;
- }
-
- - snapToGrid:(float *)x :(float *)y
- /* make sure windows lay on 64-bit boundaries */
- {
- *x = rint((*x - 4) / 64.0) * 64.0 + 4.0;
- *y = rint(*y / 64.0) * 64.0;
- return self;
- }
-
- - moveWindows:(float)dx :(float)dy
- /* move the windows dx and dy */
- {
- int numberOfWindows, startX, stopX, startY, stopY, i;
- id theList, moveWindow;
- NXRect frameRect;
- BOOL reverse;
-
- /* note that when moving to upper left, we can use the lower right */
- /* window list, just traverse it in the opposite direction */
- if (dx <= 0 && dy < 0) {
- theList = upperRight;
- reverse = YES;
- } else if (dx >= 0 && dy > 0) {
- theList = upperRight;
- reverse = NO;
- } else if (dx < 0 && dy >= 0) {
- theList = lowerRight;
- reverse = YES;
- } else { /* (dx > 0 && dy <= 0) */
- theList = lowerRight;
- reverse = NO;
- }
-
- numberOfWindows = [theList count];
-
- if (!reverse) {
- i = 0;
- while (i < numberOfWindows) {
- moveWindow = [theList objectAt:i++];
- [moveWindow getFrame:&frameRect];
- [moveWindow moveTo:(frameRect.origin.x + dx)
- :(frameRect.origin.y + dy)];
- }
- } else {
- i = numberOfWindows;
- while (i--) {
- moveWindow = [theList objectAt:i];
- [moveWindow getFrame:&frameRect];
- [moveWindow moveTo:(frameRect.origin.x + dx)
- :(frameRect.origin.y + dy)];
- }
- }
-
- return self;
- }
-
- - handleNonDock:(NXEvent *)theEvent
- /* click in a non-dock window */
- {
- port_t appPort;
- int flag;
-
- /* only concern ourselves with double clicks */
- if (theEvent->data.mouse.click == 2) {
- /* simulate NeXT dock functionality */
- highLighted = YES;
- [self display];
- [NXApp deactivateSelf];
-
- /* get the WorkSpace to make sure our app is running */
- appPort = NXPortFromName((rindex(appName, '/') + 1), NULL);
- if (appPort == PORT_NULL) {
- /* something went wrong */
- highLighted = NO;
- [self display];
- [NXApp activateSelf:YES];
- return self;
- }
- /* now unhide the app (just like the WorkSpace) */
- [[NXApp appSpeaker] setSendPort:appPort];
- [[NXApp appSpeaker] unhide];
-
- /* save our app's PostScript context (for a later version, maybe) */
- appsPSContext = [NXApp activeApp];
-
- /* all done, so show app is active and unhighlight ourselves */
- highLighted = NO;
- active = YES;
- [self display];
- }
-
- return self;
- }
-
- - hideOrUnhide
- /* hide or unhide the dock app's menu */
- {
- if (altDocAppHidden) {
- [[NXApp mainMenu] orderFront:self];
- altDocAppHidden = NO;
- } else {
- [[NXApp mainMenu] orderOut:self];
- altDocAppHidden = YES;
- }
-
- return self;
- }
-
- - (BOOL)theDock
- {
- return theDock;
- }
-
- - coordinates:(int *)xCoord :(int *)yCoord
- /* return our grid coordinates */
- {
- *xCoord = xGridLocation;
- *yCoord = yGridLocation;
- return self;
- }
-
- @end
-